using System;
using System.Collections.Generic;
using System.Text;

namespace Mysoft.Dbf
{
    public struct ColumnSpecification
        {
            public byte Position;
            public string Name;
            public string DbfType;
            public byte TotalLength;
            public byte DecimalPlaces;

            public string PropertyName
            {
                get
                {
                    string cuSpatii = this.Name.Replace("_"," ").ToLower();
                    return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(cuSpatii).Replace(" ", "") ;
                }
            }

            public string VariableName
            {
                get
                {
                    return "_" + PropertyName.ToLower()[0] + PropertyName.Substring(1);
                }
            }

            internal static ColumnSpecification FromString(string line)
            {
                string[] components = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (components.Length < 4)
                    throw new ApplicationException("Am identificat doar " + components.Length + 
                        " coloane in textul <" + line + ">. Acest text  nu poate fi interpretat drept specificatiile unei coloane ...");
                ColumnSpecification rez = new ColumnSpecification();
                rez.Position = byte.Parse(components[0]);
                rez.Name = components[1];
                rez.DbfType = components[2];
                byte.TryParse( components[3],out rez.TotalLength);
                if ( components.Length >= 5) 
                    byte.TryParse (components[4],out rez.DecimalPlaces);
                return rez;
            }

            public string DotNetType
            {
                get
                {
                    if (DbfType == "Numeric")
                        return "decimal";
                    if (DbfType == "Character")
                        return "string";
                    if (DbfType == "Logical")
                        return "boolean";
                    if (DbfType == "Date")
                        return "DateTime";
                    throw new ApplicationException("Nu stiu ce tip de date .net corespunde tipului de date dbf " + DbfType);
                }
            }

        private const string Template =
@"private <%=PropertyType%> <%=VariableName%>;
[ExportAs<%=DbfType%>Column(""<%=DbfColumnName%>""<%=TotalSizeAndDecimalPlaces%>)]
public <%=PropertyType%> <%=PropertyName%>
{
get{return <%=VariableName%>;}
set{<%=VariableName%> = value;}
}
";
            public string GetCode()
            {
                string rez = Template;
                rez = rez.Replace("<%=PropertyType%>", this.DotNetType);
                rez = rez.Replace("<%=VariableName%>", this.VariableName);
                rez = rez.Replace("<%=DbfType%>", this.DbfType);
                rez = rez.Replace("<%=DbfColumnName%>", this.Name.ToUpper().Replace(" ","_"));
                string totalSizeAndPrecision = "";
                if (DbfType == "Character")
                {
                    totalSizeAndPrecision = "," + TotalLength.ToString();
                }
                if (DbfType == "Numeric")
                {
                    totalSizeAndPrecision = "," + TotalLength.ToString() + "," + DecimalPlaces.ToString();
                }
                rez = rez.Replace("<%=TotalSizeAndDecimalPlaces%>", totalSizeAndPrecision);
                rez = rez.Replace("<%=PropertyName%>", PropertyName);
                return rez;
            }
        }

    public class ExportSpecificationsGenerator : List<ColumnSpecification>
    {
        public string GetCode(string numeClasa)
        {
            StringBuilder rez = new StringBuilder("public class " + numeClasa);
            rez.AppendLine();
            rez.Append("{");
            rez.AppendLine();
            foreach (ColumnSpecification column in this)
            {
                rez.Append( column.GetCode() );
                rez.AppendLine();
            }
            rez.AppendLine();
            rez.Append("}");
            rez.AppendLine();
            return rez.ToString();
        }

        public static ExportSpecificationsGenerator FromFoxproStructureListing(string fromStringSpecification)
        {
            if (! fromStringSpecification.Trim().StartsWith("Field  Field Name  Type       Width    Dec    Index  Collate" ) )
                throw new ApplicationException("The string specification must start with a row containing the following text : Field  Field Name  Type       Width    Dec    Index  Collate");
            fromStringSpecification = fromStringSpecification.Replace("Field  Field Name  Type       Width    Dec    Index  Collate", "");
            ExportSpecificationsGenerator rez = new ExportSpecificationsGenerator();
            string[] lines = fromStringSpecification.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in lines)
            {
                if (line.Trim().Length == 0)
                    continue;
                rez.Add(ColumnSpecification.FromString(line));
            }
            return rez;
        }

    }
}
